package com.binance.gateway.filter.auth;

import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.binance.gateway.app.base.helper.SysConfigHelper;
import com.binance.gateway.app.base.vo.CommonRet;
import com.binance.gateway.constant.GwConstants;
import com.binance.gateway.constant.GwFilterOrders;
import com.binance.gateway.filter.BaseFilter;
import com.binance.master.error.GeneralCode;
import com.binance.master.utils.RedisCacheUtils;
import com.binance.master.utils.WebUtils;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

import lombok.extern.slf4j.Slf4j;

/**
 * Created by Fei.Huang on 2018/8/24.
 */
@Component
@Slf4j
public class IpFilter extends BaseFilter {

    protected static final String SEND_FORWARD_FILTER_RAN = "sendForwardFilter.ran";

    protected static final String OFF = "off";

    private static final String IP_BLACKLIST_SWITCH = "gw_ip_black_list_switch";
    private static final String IP_BLACKLIST = "gw_ip_black_list";

    @Autowired
    private SysConfigHelper sysConfigHelper;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return GwFilterOrders.IP;
    }

    @Override
    public boolean shouldFilter() {
        Set<String> blackListIps = RedisCacheUtils.get(GwConstants.GW_IP_BLACKLIST_RDS_KEY, Set.class);
        if (CollectionUtils.isNotEmpty(blackListIps)
                || !StringUtils.equalsIgnoreCase(OFF, sysConfigHelper.getCodeByDisplayName(IP_BLACKLIST_SWITCH))) {
            return true;
        }
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        // 由SycConfig控制IP黑名单
        String userIp = WebUtils.getRequestIp();
        if (StringUtils.contains(sysConfigHelper.getCodeByDisplayName(IP_BLACKLIST), userIp)) {
            handleBlackListIp(userIp, "sysConfigIpList");
        }

        // 与RiskManagement集成，共享IP黑名单
        Set<String> blackListIps = RedisCacheUtils.get(GwConstants.GW_IP_BLACKLIST_RDS_KEY, Set.class);
        if (CollectionUtils.isNotEmpty(blackListIps) && blackListIps.contains(userIp)) {
            handleBlackListIp(userIp, "redisIpList");
        }

        return null;
    }

    private void handleBlackListIp(String userIp, String ipSource) {
        log.info("UserIp hit the ipBlackList, userIp:{}, userId:{}, ipSource:{}", userIp, super.getUserId(), ipSource);

        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.set(SEND_FORWARD_FILTER_RAN, true);
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
        CommonRet<Void> ret = baseHelper.getCommonRet(GeneralCode.SYS_ACCESS_LIMITED, ctx.getRequest());
        ctx.setResponseBody(JSON.toJSONString(ret));

        // 踢出
        super.logoutAll();
    }
}
